<?php

/**
 * 用户相关API
 * 
 * @author ShuangYa
 * @package EUser
 * @category Controller
 * @link http://www.sylingd.com/
 * @copyright Copyright (c) 2015 ShuangYa
 * @license http://lab.sylingd.com/go.php?name=euser&type=license
 */

namespace euser\controller;
use \Sy;
use \sy\base\Controller;
use \sy\lib\YHtml;
use \sy\lib\YCookie;
use \sy\lib\YSecurity;
use \euser\libs\Common;

class User extends Controller {
	public function __construct() {
		$this->u = Sy::service('user');
		$this->a = Sy::service('app');
	}
	protected function parseSdkData($requestId) {
		if (Sy::$httpRequest[$requestId]->header['x-method'] === 'SDK-HTTP') {
			//SDK方式请求
			$data = Sy::$httpRequest[$requestId]->rawContent();
			Sy::$httpRequest[$requestId]->post = json_decode($data, 1);
			$app = $this->a->getClient(Sy::$httpRequest[$requestId]->post['client_id']);
			$sign = $this->a->createSign($data, $app['secret']);
			if ($sign !== Sy::$httpRequest[$requestId]->header['x-sign']) {
				Sy::setMimeType('json', $requestId);
				Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_sign']));
				return FALSE;
			}
			return TRUE;
		}
	}
	//[API]获取用户信息
	public function actionInfo($requestId = NULL, $apiData = FALSE) {
		if (!$apiData) {
			if (Sy::$httpRequest[$requestId]->header['x-method'] !== 'SDK-HTTP') {
				return;
			}
			if (!$this->parseSdkData($requestId)) {
				return;
			}
			Sy::setMimeType('json', $requestId);
			if (isset(Sy::$httpRequest[$requestId]->post['uid'])) {
				$id = Sy::$httpRequest[$requestId]->post['uid'];
			} elseif (isset(Sy::$httpRequest[$requestId]->post['name'])) {
				$id = $this->u->genUid(Sy::$httpRequest[$requestId]->post['name']);
			} else {
				Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_id']));
				return;
			}
		} else {
			if (isset($apiData['uid'])) {
				$id = $apiData['uid'];
			} elseif (isset($apiData['name'])) {
				$id = $this->u->genUid($apiData['name']);
			} else {
				return ['error' => 'invalid_id'];
				return;
			}
		}
		$user = $this->u->get($id);
		$user['_id'] = strval($user['_id']);
		unset($user['password']);
		if ($apiData) {
			return $user;
		} else {
			Sy::$httpResponse[$requestId]->write(Common::getAjax($user));
		}
	}
	//[API]检查Token有效情况
	public function actionGetToken($requestId = NULL, $apiData = NULL) {
		if (!$apiData) {
			if (Sy::$httpRequest[$requestId]->header['x-method'] !== 'SDK-HTTP') {
				return;
			}
			if (!$this->parseSdkData($requestId)) {
				return;
			}
			Sy::setMimeType('json', $requestId);
			$token = $this->u->getToken(Sy::$httpRequest[$requestId]->post['token']);
			if (isset(Sy::$httpRequest[$requestId]->post['tverify'])) {
				$tverify = Sy::$httpRequest[$requestId]->post['tverify'];
			}
		} else {
			$token = $this->u->getToken($apiData['token']);
			if ($apiData['tverify']) {
				$tverify = $apiData['tverify'];
			}
		}
		if (isset($tverify) && $token['tverify'] !== $tverify) {
			$result = ['error' => 'invalid_token'];
			if ($apiData) {
				return $result;
			} else {
				Sy::$httpResponse[$requestId]->write(Common::getAjax($result));
				return;
			}
		}
		$token['_id'] = strval($token['_id']);
		if ($token === FALSE) {
			$result = ['error' => 'invalid_token'];
			if ($apiData) {
				return $result;
			} else {
				Sy::$httpResponse[$requestId]->write(Common::getAjax($result));
				return;
			}
		} else {
			$result = ['token' => $token];
			if ($apiData) {
				return $result;
			} else {
				Sy::$httpResponse[$requestId]->write(Common::getAjax($result));
			}
		}
	}
	//[API]添加用户
	public function actionAdd($requestId = NULL, $apiData = NULL) {
		if (!$apiData) {
			if (Sy::$httpRequest[$requestId]->header['x-method'] !== 'SDK-HTTP') {
				return;
			}
			if (!$this->parseSdkData($requestId)) {
				return;
			}
			Sy::setMimeType('json', $requestId);
			$client_id = Sy::$httpRequest[$requestId]->post['client_id'];
			$user = Sy::$httpRequest[$requestId]->post['user'];
		} else {
			$client_id = $apiData['client_id'];
			$user = $apiData['user'];
		}
		//并非所有应用都有添加用户的权限
		$app = $this->a->getClient($client_id);
		if (!is_array($app['scope']) || !in_array('user_add', $app['scope'], TRUE)) {
			$result = ['error' => 'access_denied'];
			if ($apiData) {
				return $result;
			} else {
				Sy::$httpResponse[$requestId]->write(Common::getAjax($result));
				return;
			}
		}
		if (!isset($user['name']) || !isset($user['password'])) {
			$result = ['error' => 'invalid_param'];
			if ($apiData) {
				return $result;
			} else {
				Sy::$httpResponse[$requestId]->write(Common::getAjax($result));
				return;
			}
		}
		$uid = $this->u->add($user);
		$result = ['id' => $uid];
		if ($apiData) {
			return $result;
		} else {
			Sy::$httpResponse[$requestId]->write(Common::getAjax($result));
		}
	}
	//通用登录验证页面
	public function actionLogin($requestId = NULL) {
		if (Sy::$httpRequest[$requestId]->server['request_method'] === 'POST') {
			//根据AppID判断客户端类型
			if (!isset(Sy::$httpRequest[$requestId]->post['appid'])) {
				Sy::setMimeType('json', $requestId);
				Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_appid']));
				return;
			}
			$app = $this->a->getClient(Sy::$httpRequest[$requestId]->post['appid']);
			if (!isset($app['type'])) {
				Sy::setMimeType('json', $requestId);
				Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_appid']));
				return;
			}
			//判断客户端类型
			if ($app['type'] === 'client') {
				//客户端形式
				//检查签名
				$signKey = $app['secret'];
				$signStr = $this->a->createSign(file_get_contents('php://input'), $signKey);
				if ($signStr !== Sy::$httpRequest[$requestId]->header['x-sign']) {
					Sy::setMimeType('json', $requestId);
					Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_sign']));
					return;
				}
				$v = $this->u->verify(Sy::$httpRequest[$requestId]->post['user'], Sy::$httpRequest[$requestId]->post['password']);
				if ($v === FALSE) {
					Sy::setMimeType('json', $requestId);
					Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_password']));
					return;
				}
				list($token, $tverify) = $this->u->createToken($v);
				Sy::setMimeType('json', $requestId);
				Sy::$httpResponse[$requestId]->write(Common::getAjax(['token' => $token, 'tverify' => 'tverify']));
				return;
			} else {
				//Web形式
				//CSRF检查
				YSecurity::csrfVerify(TRUE, $requestId);
				$v = $this->u->verify(Sy::$httpRequest[$requestId]->post['user'], Sy::$httpRequest[$requestId]->post['password']);
				if ($v === FALSE) {
					Sy::setMimeType('json', $requestId);
					Sy::$httpResponse[$requestId]->write(Common::getAjax(['error' => 'invalid_password']));
					return;
				}
				//验证Cookie中的token是否有效
				$token = $this->u->verifyCookie($requestId);
				if (FALSE === $token || $token['user'] !== $this->u->genUid(Sy::$httpRequest[$requestId]->post['user'])) {
					list($token, $tverify) = $this->u->createToken($v);
					//获取根域名
					//将会排除IP形式的干扰
					if (preg_match('/([a-z0-9\-_]+)\.(com|net|edu|org|gov)\.([a-z]{1,5})$/i', Sy::$httpRequest[$requestId]->header['host'], $rootDomain) || preg_match('/([a-z0-9\-_]+)\.([a-z]{1,5})$/i', Sy::$httpRequest[$requestId]->header['host'], $rootDomain)) {
						YCookie::set(['name' => 'token', 'value' => $token, 'path' => '/', 'expire' => 3600 * 24 * 7, 'domain' => '.' . $rootDomain[0], 'httponly' => TRUE, 'requestId' => $requestId]);
						YCookie::set(['name' => 'tverify', 'value' => $tverify, 'path' => '/', 'expire' => 3600 * 24 * 7, 'domain' => '.' . $rootDomain[0], 'httponly' => TRUE, 'requestId' => $requestId]);
					} else {
						YCookie::set(['name' => 'token', 'value' => $token, 'path' => '/', 'expire' => 3600 * 24 * 7, 'httponly' => TRUE, 'requestId' => $requestId]);
						YCookie::set(['name' => 'tverify', 'value' => $tverify, 'path' => '/', 'expire' => 3600 * 24 * 7, 'httponly' => TRUE, 'requestId' => $requestId]);
					}
				}
				Sy::setMimeType('json', $requestId);
				Sy::$httpResponse[$requestId]->write(Common::getAjax());
				return;
			}
		} else {
			//基本样式
			$width = isset(Sy::$httpRequest[$requestId]->get['width']) ? Sy::$httpRequest[$requestId]->get['width'] : 300;
			//参数
			$css = isset(Sy::$httpRequest[$requestId]->get['css']) ? Sy::$httpRequest[$requestId]->get['css'] : NULL;
			$style = isset(Sy::$httpRequest[$requestId]->get['style']) ? intval(Sy::$httpRequest[$requestId]->get['style']) : 0;
			$callback = isset(Sy::$httpRequest[$requestId]->get['callback']) ? Sy::$httpRequest[$requestId]->get['callback'] : 'loginCallback'; //回调
			if (!is_file(Sy::viewPath('user/login/style_' . $style))) {
				$style = 0;
			}
			//检查是否已经登录
			$token = $this->u->verifyCookie($requestId);
			$isLogin = (FALSE === $token ? 0 : 1);
			$uid = ($isLogin ? $token['user'] : NULL);
			//OAuth列表
			$oauthlist = unserialize(file_get_contents(Sy::$appDir . 'data/oauth.serialize'));
			//其他参数
			$appid = Sy::$httpRequest[$requestId]->get['appid'];
			$result = Sy::view('user/login/style_' . $style, ['css' => $css, 'width' => $width, 'callback' => $callback, 'isLogin' => $isLogin, 'uid' => $uid, 'oauth' => $oauthlist, 'appid' => $appid]);
			Sy::setMimeType('html', $requestId);
			Sy::$httpResponse[$requestId]->write($result);
			return;
		}
	}
	//通用注销页面
	public function actionLoginout($requestId = NULL) {
		if (preg_match('/([a-z0-9\-_]+)\.(com|net|edu|org|gov)\.([a-z]{1,5})$/i', Sy::$httpRequest[$requestId]->header['host'], $rootDomain) || preg_match('/([a-z0-9\-_]+)\.([a-z]{1,5})$/i', Sy::$httpRequest[$requestId]->header['host'], $rootDomain)) {
			YCookie::set(['name' => 'token', 'value' => 'loginout', 'path' => '/', 'expire' => -1, 'domain' => '.' . $rootDomain[0], 'httponly' => TRUE, 'requestId' => $requestId]);
			YCookie::set(['name' => 'tverify', 'value' => 'loginout', 'path' => '/', 'expire' => -1, 'domain' => '.' . $rootDomain[0], 'httponly' => TRUE, 'requestId' => $requestId]);
		} else {
			YCookie::set(['name' => 'token', 'value' => 'loginout', 'path' => '/', 'expire' => -1, 'httponly' => TRUE, 'requestId' => $requestId]);
			YCookie::set(['name' => 'tverify', 'value' => 'loginout', 'path' => '/', 'expire' => -1, 'httponly' => TRUE, 'requestId' => $requestId]);
		}
		$redirect = isset(Sy::$httpRequest[$requestId]->get['redirect']) ? Sy::$httpRequest[$requestId]->get['redirect'] : Sy::createUrl('user/loginPage');
		Sy::$httpResponse[$requestId]->header('Location', $redirect);
	}
	//从客户端直接登陆到Web
	public function actionOnekeyLogin($requestId = NULL) {
		return; //暂不使用
		//根据AppID判断客户端类型
		if (!isset(Sy::$httpRequest[$requestId]->post['appid'])) {
			Common::showAjax(['error' => 'invalid_appid']);
		}
		$app = $this->a->getClient(Sy::$httpRequest[$requestId]->post['appid']);
		if (!isset($app['type'])) {
			Common::showAjax(['error' => 'invalid_appid']);
		}
		//判断客户端类型
		if ($app['type'] !== 'client') {
			Common::showAjax(['error' => 'invalid_app_type']);
		}
		//解密
		$signKey = $app['secret'];
		$jsonStr = YSecurity::securityCode(Sy::$httpRequest[$requestId]->server['query_string'], 'DECODE', $signKey);
		if (empty($jsonStr)) {
			Common::showAjax(['error' => 'invalid_sign']);
		}
		$json = json_decode($jsonStr, 1);
		//判断token是否有效
		if (FALSE === ($token = $this->u->getToken($json['token']))) {
			Common::showAjax(['error' => 'invalid_token']);
		}
		//设置Cookie
		if (preg_match('/([a-z0-9\-_]+)\.(com|net|edu|org|gov)\.([a-z]{1,5})$/i', Sy::$httpRequest[$requestId]->server['http_host'], $rootDomain) || preg_match('/([a-z0-9\-_]+)\.([a-z]{1,5})$/i', Sy::$httpRequest[$requestId]->server['http_host'], $rootDomain)) {
			YCookie::set(['name' => 'token', 'value' => $json['token'], 'path' => '/', 'expire' => 3600 * 24 * 7, 'domain' => '.' . $rootDomain[0], 'httponly' => TRUE]);
			YCookie::set(['name' => 'token', 'value' => $json['token'], 'path' => '/', 'expire' => 3600 * 24 * 7, 'domain' => '.' . $rootDomain[0], 'httponly' => TRUE]);
		} else {
			YCookie::set(['name' => 'token', 'value' => $json['token'], 'path' => '/', 'expire' => 3600 * 24 * 7, 'httponly' => TRUE]);
			YCookie::set(['name' => 'token', 'value' => $json['token'], 'path' => '/', 'expire' => 3600 * 24 * 7, 'httponly' => TRUE]);
		}
		header('Location: ' . $json['redirect']);
	}
	//一般登陆页面，类似于passport
	public function actionLoginPage($requestId = NULL) {
		//跳转
		$redirect = isset(Sy::$httpRequest[$requestId]->get['redirect']) ? Sy::$httpRequest[$requestId]->get['redirect'] : Sy::createUrl('user/home');
		$result = Sy::view('user/login/page', ['redirect' => $redirect]);
		Sy::setMimeType('html', $requestId);
		Sy::$httpResponse[$requestId]->write($result);
	}
}
